//
// Created by baigui on 2021/10/23.
//

#ifndef SIMPLE_PLAYER_BASESTREAM_H
#define SIMPLE_PLAYER_BASESTREAM_H


#include <cstdio>
#include "block.h"

class BaseStream {

public:

    ssize_t sp_stream_Peek(uint8_t **bufp, size_t len);

    block_t *sp_stream_ReadBlock();

    ssize_t sp_stream_Read(void *buf, size_t len);

    uint64_t sp_stream_Tell();

    int sp_stream_Seek(uint64_t offset);

    int sp_stream_vaControl(int cmd, va_list args);

    block_t *sp_stream_Block(size_t size );

protected:
    /**
     * Read data.
     *
     * Callback to read data from the stream into a caller-supplied buffer.
     *
     * This may be NULL if the stream is actually a directory rather than a
     * byte stream, or if \ref stream_t.block is non-NULL.
     *
     * \param buf buffer to read data into
     * \param len buffer length (in bytes)
     *
     * \retval -1 no data available yet
     * \retval 0 end of stream (incl. fatal error)
     * \retval positive number of bytes read (no more than len)
     */
    virtual ssize_t read(void *buf, size_t len) = 0;

    /**
     * Read data block.
     *
     * Callback to read a block of data. The data is read into a block of
     * memory allocated by the stream. For some streams, data can be read more
     * efficiently in block of a certain size, and/or using a custom allocator
     * for buffers. In such case, this callback should be provided instead of
     * \ref stream_t.read; otherwise, this should be NULL.
     *
     * \param eof storage space for end-of-stream flag [OUT]
     * (*eof is always false when invoking block(); block() should set
     *  *eof to true if it detects the end of the stream)
     *
     * \return a data block,
     * NULL if no data available yet, on error and at end-of-stream
     */
    virtual block_t *read_block(bool *eof) = 0;

//    /**
//     * Read directory.
//     *
//     * Callback to fill an item node from a directory
//     * (see doc/browsing.txt for details).
//     *
//     * NULL if the stream is not a directory.
//     */
//    virtual  int  readdir(input_item_node_t *) = 0;

    /**
     * Seek.
     *
     * Callback to set the stream pointer (in bytes from start).
     *
     * May be NULL if seeking is not supported.
     */
    virtual int seek(uint64_t) = 0;

    /**
     * Stream control.
     *
     * Cannot be NULL.
     *
     * \see stream_query_e
     */
    virtual int  control(int i_query, va_list) = 0;


protected:
    char        *psz_name;
    char        *psz_url; /**< Full URL or MRL (can be NULL) */
    const char  *psz_location; /**< Location (URL with the scheme stripped) */
    char        *psz_filepath; /**< Local file path (if applicable) */
    bool         b_preparsing; /**< True if this access is used to preparse */

    /*
     * 真实读取内容。
     */
    ssize_t sp_stream_ReadRaw(void *buf, size_t len);

    ssize_t sp_stream_CopyBlock(block_t * pp,
                                 void *buf, size_t len);

    ssize_t sp_stream_ReadPartial(void *buf, size_t len);

private:
    block_t *peek = nullptr;
    uint64_t offset;
    bool eof;


};


#endif //SIMPLE_PLAYER_BASESTREAM_H
